/**
 * 
 */
package br.com.skynix.tcmc.base.spring;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.primefaces.model.SortOrder;
import org.springframework.transaction.annotation.Transactional;

import br.com.skynix.tcmc.base.excecao.MensagemErro;
import br.com.skynix.tcmc.base.excecao.NegocioException;
import br.com.skynix.tcmc.base.model.EntidadeAuditavel;
import br.com.skynix.tcmc.model.rh.Empresa;

/**
 * @author mgrb
 * 
 */
@Transactional(readOnly = true)
public abstract class AbstractServiceImpl<T extends EntidadeAuditavel> {

	/**
	 * Inseri um novo registro no banco de dados
	 * @param entidade instancia de {@link Entidade}
	 * @return Novo ID da entidade.
	 */
	@Transactional(readOnly = false)
	public Long inserir(T entidade) {
		validarEntidade(entidade);
		return getDao().inserir(entidade);
	}

	/**
	 * @param entidade
	 */
	private void validarEntidade(T entidade) {
		List<MensagemErro> erros = validarInserirAlterar(entidade);
		if (!erros.isEmpty()) {
			throw new NegocioException(erros);
		}
	}

	/**
	 * Atualiza a entidade no banco de dados.
	 */
	@Transactional(readOnly = false)
	public void alterar(T entidade) {
		validarEntidade(entidade);
		getDao().alterar(entidade);
	}

	/**
	 * @param entidade
	 * @return
	 */
	protected List<MensagemErro> validarInserirAlterar(T entidade) {
		return new ArrayList<MensagemErro>();

	}

	@Transactional(readOnly = false)
	public void excluir(T entidade) {
		List<MensagemErro> erros = validarExclusao(entidade);
		if (!erros.isEmpty()) {
			throw new NegocioException(erros);
		}
		entidade.setAtivo(false);
		entidade.setDeletado(true);
		getDao().alterar(entidade);
	}

	/**
	 * @param entidade
	 */
	protected List<MensagemErro> validarExclusao(T entidade) {
		return new ArrayList<MensagemErro>();

	}

	/**
	 * Carrega uma instancia de {@link Entidade} do banco de dados apartir da
	 * chave primaria.
	 */

	public T buscarPelaChave(Long id) {
		return getDao().buscarPelaChave(id);

	}

	/**
	 * @return uma instancia de {@link AbstractDao}.
	 */
	protected abstract AbstractDao<T> getDao();

	public Integer getVersaoAtual(Long id) {
		return getDao().getVersaoAtual(id);

	}

	public List<T> buscarPeloExemplo(T entidadeExemplo) {
		return getDao().buscarPeloExemplo(entidadeExemplo);
	}

	/**
	 * 
	 */
	public List<T> listarTodos() {
		return getDao().listarTodos();
	}

	/**
	 * @param modelo
	 * @param first
	 * @param pageSize
	 * @param sortField
	 * @param sortOrder
	 * @return
	 */
	public List<T> buscarPeloExemplo(T modelo, int first, int pageSize,
			String sortField, SortOrder sortOrder) {
		return getDao().buscarPeloExemplo(modelo, first, pageSize, sortField,
				sortOrder);
	}

	/**
	 * @param modelo
	 * @return
	 */
	public int getQuantidadeRegistros(T modelo) {
		return getDao().getQuantidadeRegistros(modelo);
	}

	public List<T> listarTodos(Empresa empresa) {
		return empresa == null ? Collections.EMPTY_LIST : getDao().listarTodos(
				empresa);
	}

}
